# Each team member would need to set their directory path to variable "project_dir"
# we will make sure everything else is relative to "project_dir"
project_dir <- "/home/admin-12/Documents/IMARTICUS/Data-Riders/EDA"
setwd(project_dir)
# Setup Packages
load_packages <- function () {
# Imports
packages <- c("VIM", "dplyr", "plotly", "psych", "corrplot", "cluster", "factoextra", "psych")
installed_packages <- packages %in% rownames(installed.packages())
if (any(installed_packages == FALSE)) {
install.packages(packages[!installed_packages])
}
# Packages loading with suppressed messages
suppressMessages(invisible(lapply(packages, library, character.only = TRUE)))
}
load_packages()
# Get the Raw Data from the file
read_file <- function () {
data <- read.csv("data/cereals_data.csv")
return (data)
}
# Handle missing values
handle_missing_values <- function (input) {
output <- input
output <- kNN(output)
return (output)
}
# Clearn the data to make it good for processing
# eg. delete unwanted rows, change data types etc
data_processing <- function (input) {
output <- input
output <- handle_missing_values(output)
# Set company names
output$mfr_names <- as.character(output$mfr)
output$mfr_names[output$mfr_names=="A"] <- "American Home Food Products"
output$mfr_names[output$mfr_names=="G"] <- "General Mills"
output$mfr_names[output$mfr_names=="K"] <- "Kelloggs"
output$mfr_names[output$mfr_names=="N"] <- "Nabisco"
output$mfr_names[output$mfr_names=="P"] <- "Post"
output$mfr_names[output$mfr_names=="Q"] <- "Quaker Oats"
output$mfr_names[output$mfr_names=="R"] <- "Ralston Purina"
output$mfr_names_factor = as.factor(output$mfr_names)
# Calorie Categories
output <- within(output, {
calories_category <- NA
calories_category[calories>=50&calories<80] <- "L"
calories_category[calories>=80&calories<110] <- "M"
calories_category[calories>=110] <- "H"
})
# some data processing steps that would be required
return (output)
}
# Get the Data Frame for the data
get_data <- function () {
raw <- read_file()
data <- data_processing(raw)
return (data)
}
data <- get_data()
data_grp_mfr <- data %>% group_by(mfr_names_factor)
Part #: Understanding Variables
Overall View
draw_density_plot <- function (value_set, xlab) {
skewness <- round(skew(value_set), 2)
mean <- round(mean(value_set), 2)
median <- round(median(value_set), 2)
title <- paste(xlab, "Density Chart | ", "Skewness:", skewness)
plot(density(value_set), ylab = "Probabilty Density", xlab = xlab, main=title,)
abline(v=mean, col="red")
abline(v=median, col="blue")
}
Distribution of Calories (in the Products)
draw_density_plot(data$calories, "Calories")

Distribution of Ratings (for the Products)
draw_density_plot(data$rating, "Rating")

Relationship of one variable with another
cor_result <- cor((data_grp_mfr %>% select_if(is.numeric))[-1])
corrplot(cor_result)

heatmap(cor_result)

good_bad_corr <- function (cor_result_filter) {
#cor_result_filter <-
cor_result_filter_names <- names(cor_result_filter)
names(cor_result_filter) <- NULL
cor_result_df <- data.frame(cor_result_filter_names, cor_result_filter) %>% arrange(cor_result_filter)
names(cor_result_df) <- c("Parameters", "Corellation")
ggplot(cor_result_df, aes(x=Parameters, y=Corellation)) + geom_bar(stat = "identity") +
theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"))
}
Influencers for Ratings
good_bad_corr(cor_result["rating",])

Influencers for Calories
good_bad_corr(cor_result["calories",])

Whats you get in one Serving
data %>% ggplot(aes(x = cups, fill = mfr_names)) +
geom_histogram() +
scale_x_continuous(name = "# of Cups", expand = c(0,0)) +
labs(fill = "Manufacturer", title = "Distribution of cups per Serving",
subtitle = "different cups for servings", y="# of Products") +
theme_classic() + scale_fill_brewer(palette="Dark2")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

data %>% ggplot(aes(x = weight, fill = mfr_names)) + geom_histogram() +
scale_x_continuous(name = "Weight (in ounces)", expand = c(0,0)) +
labs(fill = "Manufacturer", title = "Distribution of Weight per Serving", subtitle = "Weight per serving") +
theme_classic() + scale_fill_brewer(palette="Dark2")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Best in the Market
d <- data %>% arrange(rating) %>% head(4) %>% select(name, rating)
ggplot(data=d, aes(x=name, y=rating)) + geom_bar(stat = "identity") +
labs(y="Ratings") + scale_fill_brewer(palette="Dark2") +
theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"))

Part #:
Company wise Rating Consistency
data_grp_mfr %>% plot_ly(y= ~rating, x= ~mfr_names_factor, type = "box", color= ~mfr_names_factor) %>%
layout(title="Product Consistency", xaxis=list(title="Manufactures"), yaxis=list(title="Rating"))
Company wise Calorie Consistency
data_grp_mfr %>% plot_ly(y= ~calories, x= ~mfr_names_factor, type = "box", color= ~mfr_names_factor) %>%
layout(title="Product Consistency (by Calories)", xaxis=list(title="Manufactures"), yaxis=list(title="Calories"))
Part #:
Distribution of Rating vs Calorie Category
data %>% ggplot(aes(x = rating, fill = calories_category)) + geom_histogram() + scale_fill_brewer(palette = "Set1") +
scale_x_continuous(name = "Ratings", expand = c(0,0)) +
labs(fill = " Cal ", y ='Count', title = "Distribution of Rating vs Calorie Category", subtitle = "Low rating for High calories") +
theme_classic()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Word Cloud (error in markdown)
#get_file_content <- function () {
# txt <- readLines("data/health.txt")
# txt <- paste(txt, collapse = " ")
# txt <- tolower(txt)
# txt <- gsub("[^a-zA-Z]", " ", txt)
# txt <- gsub("\\s+", " ", txt)
# txt <- removeWords(txt, stopwords())
# words <- strsplit(txt, " ")
# word_freq <- table(words)
# return (word_freq)
#}
#word_freq <- get_file_content()
#wordcloud2(word_freq, size=10)
Cluster Analysis
cluster_data <- data %>% select(calories, rating, protein, fat) %>% scale
row.names(cluster_data) <- data[,1]
km.res <- kmeans(cluster_data, 5, nstart = 25)
fviz_cluster(km.res, data=cluster_data, palette = "jco", ggtheme = theme_minimal())

LS0tCnRpdGxlOiAiRGF0YSBSaWRlcnMgTm90ZWJvb2siCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCmg1IHsKICAgIGJhY2tncm91bmQ6IHJnYmEoMTA4LCAxMDgsIDEwOCwgMC4zNSk7CiAgICBib3JkZXItdG9wOiAxcHggc29saWQgIzg0ODQ4NDsKICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjODQ4NDg0OwogICAgbWFyZ2luLXRvcDogMHB4OwogICAgcGFkZGluZzogMTBweCAxMHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KaDU6aG92ZXIgewogIGJhY2tncm91bmQ6ICNmZmViM2I7Cn0KCmgyIHsKICBiYWNrZ3JvdW5kOiAjMjEyMTIxOwogIGNvbG9yOiB3aGl0ZTsKICBwYWRkaW5nOiA4cHggOHB4OwogIG1hcmdpbi10b3A6IDBweDsKICBtYXJnaW4tYm90dG9tOiAwcHg7Cn0KCi5jb250YWluZXItcGFydCB7CiAgYm9yZGVyOiAxcHggc29saWQgI2EyYTJhMjsKICBtYXJnaW4tYm90dG9tOiAzNXB4Owp9CgoubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTMwMHB4OwogIG1hcmdpbi1sZWZ0OiBhdXRvOwogIG1hcmdpbi1yaWdodDogYXV0bzsKfQo8L3N0eWxlPgoKYGBge3J9CiMgRWFjaCB0ZWFtIG1lbWJlciB3b3VsZCBuZWVkIHRvIHNldCB0aGVpciBkaXJlY3RvcnkgcGF0aCB0byB2YXJpYWJsZSAicHJvamVjdF9kaXIiCiMgd2Ugd2lsbCBtYWtlIHN1cmUgZXZlcnl0aGluZyBlbHNlIGlzIHJlbGF0aXZlIHRvICJwcm9qZWN0X2RpciIKcHJvamVjdF9kaXIgPC0gIi9ob21lL2FkbWluLTEyL0RvY3VtZW50cy9JTUFSVElDVVMvRGF0YS1SaWRlcnMvRURBIgpzZXR3ZChwcm9qZWN0X2RpcikKCiMgU2V0dXAgUGFja2FnZXMKbG9hZF9wYWNrYWdlcyA8LSBmdW5jdGlvbiAoKSB7CiAgIyBJbXBvcnRzCiAgcGFja2FnZXMgPC0gYygiVklNIiwgImRwbHlyIiwgInBsb3RseSIsICJwc3ljaCIsICJjb3JycGxvdCIsICJjbHVzdGVyIiwgImZhY3RvZXh0cmEiLCAicHN5Y2giKQogIGluc3RhbGxlZF9wYWNrYWdlcyA8LSBwYWNrYWdlcyAlaW4lIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKQogIGlmIChhbnkoaW5zdGFsbGVkX3BhY2thZ2VzID09IEZBTFNFKSkgewogICAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlc1shaW5zdGFsbGVkX3BhY2thZ2VzXSkKICB9CiAgIyBQYWNrYWdlcyBsb2FkaW5nIHdpdGggc3VwcHJlc3NlZCBtZXNzYWdlcwogIHN1cHByZXNzTWVzc2FnZXMoaW52aXNpYmxlKGxhcHBseShwYWNrYWdlcywgbGlicmFyeSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkpCn0KbG9hZF9wYWNrYWdlcygpCgojIEdldCB0aGUgUmF3IERhdGEgZnJvbSB0aGUgZmlsZQpyZWFkX2ZpbGUgPC0gZnVuY3Rpb24gKCkgewogIGRhdGEgPC0gcmVhZC5jc3YoImRhdGEvY2VyZWFsc19kYXRhLmNzdiIpCiAgcmV0dXJuIChkYXRhKQp9CgojIEhhbmRsZSBtaXNzaW5nIHZhbHVlcwpoYW5kbGVfbWlzc2luZ192YWx1ZXMgPC0gZnVuY3Rpb24gKGlucHV0KSB7CiAgb3V0cHV0IDwtIGlucHV0CiAgb3V0cHV0IDwtIGtOTihvdXRwdXQpCiAgcmV0dXJuIChvdXRwdXQpCn0KCiMgQ2xlYXJuIHRoZSBkYXRhIHRvIG1ha2UgaXQgZ29vZCBmb3IgcHJvY2Vzc2luZwojIGVnLiBkZWxldGUgdW53YW50ZWQgcm93cywgY2hhbmdlIGRhdGEgdHlwZXMgZXRjCmRhdGFfcHJvY2Vzc2luZyA8LSBmdW5jdGlvbiAoaW5wdXQpIHsKICBvdXRwdXQgPC0gaW5wdXQKICBvdXRwdXQgPC0gaGFuZGxlX21pc3NpbmdfdmFsdWVzKG91dHB1dCkKCiAgIyBTZXQgY29tcGFueSBuYW1lcwogIG91dHB1dCRtZnJfbmFtZXMgPC0gYXMuY2hhcmFjdGVyKG91dHB1dCRtZnIpCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iQSJdIDwtICJBbWVyaWNhbiBIb21lIEZvb2QgUHJvZHVjdHMiCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iRyJdIDwtICJHZW5lcmFsIE1pbGxzIgogIG91dHB1dCRtZnJfbmFtZXNbb3V0cHV0JG1mcl9uYW1lcz09IksiXSA8LSAiS2VsbG9nZ3MiCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iTiJdIDwtICJOYWJpc2NvIgogIG91dHB1dCRtZnJfbmFtZXNbb3V0cHV0JG1mcl9uYW1lcz09IlAiXSA8LSAiUG9zdCIKICBvdXRwdXQkbWZyX25hbWVzW291dHB1dCRtZnJfbmFtZXM9PSJRIl0gPC0gIlF1YWtlciBPYXRzIgogIG91dHB1dCRtZnJfbmFtZXNbb3V0cHV0JG1mcl9uYW1lcz09IlIiXSA8LSAiUmFsc3RvbiBQdXJpbmEiCiAgb3V0cHV0JG1mcl9uYW1lc19mYWN0b3IgPSBhcy5mYWN0b3Iob3V0cHV0JG1mcl9uYW1lcykKCiAgIyBDYWxvcmllIENhdGVnb3JpZXMKICBvdXRwdXQgPC0gd2l0aGluKG91dHB1dCwgewogICAgY2Fsb3JpZXNfY2F0ZWdvcnkgPC0gTkEKICAgIGNhbG9yaWVzX2NhdGVnb3J5W2NhbG9yaWVzPj01MCZjYWxvcmllczw4MF0gPC0gIkwiCiAgICBjYWxvcmllc19jYXRlZ29yeVtjYWxvcmllcz49ODAmY2Fsb3JpZXM8MTEwXSA8LSAiTSIKICAgIGNhbG9yaWVzX2NhdGVnb3J5W2NhbG9yaWVzPj0xMTBdIDwtICJIIgogIH0pCgogICMgc29tZSBkYXRhIHByb2Nlc3Npbmcgc3RlcHMgdGhhdCB3b3VsZCBiZSByZXF1aXJlZAogIHJldHVybiAob3V0cHV0KQp9CgojIEdldCB0aGUgRGF0YSBGcmFtZSBmb3IgdGhlIGRhdGEKZ2V0X2RhdGEgPC0gZnVuY3Rpb24gKCkgewogIHJhdyA8LSByZWFkX2ZpbGUoKQogIGRhdGEgPC0gZGF0YV9wcm9jZXNzaW5nKHJhdykKICByZXR1cm4gKGRhdGEpCn0KCmRhdGEgPC0gZ2V0X2RhdGEoKQpkYXRhX2dycF9tZnIgPC0gZGF0YSAlPiUgZ3JvdXBfYnkobWZyX25hbWVzX2ZhY3RvcikKYGBgCgo8IS0tIC0tLS0tLS0tLS0gLS0tLS0tLS0tLSAtLS0tLS0tLS0tIC0tLS0tLS0tLS0gLS0+CjxkaXYgY2xhc3M9ImNvbnRhaW5lci1wYXJ0Ij4KPGgyPlBhcnQgIzogVW5kZXJzdGFuZGluZyBWYXJpYWJsZXM8L2gxPgoKPGg1Pk92ZXJhbGwgVmlldzwvaDU+CgpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXNjcmliZShkYXRhICU+JSBzZWxlY3RfaWYoaXMubnVtZXJpYykpCmBgYAoKYGBge3J9CmRyYXdfZGVuc2l0eV9wbG90IDwtIGZ1bmN0aW9uICh2YWx1ZV9zZXQsIHhsYWIpIHsKICBza2V3bmVzcyA8LSByb3VuZChza2V3KHZhbHVlX3NldCksIDIpCiAgbWVhbiA8LSByb3VuZChtZWFuKHZhbHVlX3NldCksIDIpCiAgbWVkaWFuIDwtIHJvdW5kKG1lZGlhbih2YWx1ZV9zZXQpLCAyKQogIHRpdGxlIDwtIHBhc3RlKHhsYWIsICJEZW5zaXR5IENoYXJ0ICAgfCAgIiwgIlNrZXduZXNzOiIsIHNrZXduZXNzKQogIHBsb3QoZGVuc2l0eSh2YWx1ZV9zZXQpLCB5bGFiID0gIlByb2JhYmlsdHkgRGVuc2l0eSIsIHhsYWIgPSB4bGFiLCBtYWluPXRpdGxlLCkKICBhYmxpbmUodj1tZWFuLCBjb2w9InJlZCIpCiAgYWJsaW5lKHY9bWVkaWFuLCBjb2w9ImJsdWUiKQp9CmBgYAoKPGg1PkRpc3RyaWJ1dGlvbiBvZiBDYWxvcmllcyAoaW4gdGhlIFByb2R1Y3RzKTwvaDU+CmBgYHtyfQpkcmF3X2RlbnNpdHlfcGxvdChkYXRhJGNhbG9yaWVzLCAiQ2Fsb3JpZXMiKQpgYGAKCjxoNT5EaXN0cmlidXRpb24gb2YgUmF0aW5ncyAoZm9yIHRoZSBQcm9kdWN0cyk8L2g1PgpgYGB7cn0KZHJhd19kZW5zaXR5X3Bsb3QoZGF0YSRyYXRpbmcsICJSYXRpbmciKQpgYGAKCjxoNT5SZWxhdGlvbnNoaXAgb2Ygb25lIHZhcmlhYmxlIHdpdGggYW5vdGhlcjwvaDU+CmBgYHtyfQpjb3JfcmVzdWx0IDwtIGNvcigoZGF0YV9ncnBfbWZyICU+JSBzZWxlY3RfaWYoaXMubnVtZXJpYykpWy0xXSkKY29ycnBsb3QoY29yX3Jlc3VsdCkKaGVhdG1hcChjb3JfcmVzdWx0KQpgYGAKCmBgYHtyfQpnb29kX2JhZF9jb3JyIDwtIGZ1bmN0aW9uIChjb3JfcmVzdWx0X2ZpbHRlcikgewogICNjb3JfcmVzdWx0X2ZpbHRlciA8LQogIGNvcl9yZXN1bHRfZmlsdGVyX25hbWVzIDwtIG5hbWVzKGNvcl9yZXN1bHRfZmlsdGVyKQogIG5hbWVzKGNvcl9yZXN1bHRfZmlsdGVyKSA8LSBOVUxMCiAgY29yX3Jlc3VsdF9kZiA8LSBkYXRhLmZyYW1lKGNvcl9yZXN1bHRfZmlsdGVyX25hbWVzLCBjb3JfcmVzdWx0X2ZpbHRlcikgJT4lIGFycmFuZ2UoY29yX3Jlc3VsdF9maWx0ZXIpCiAgbmFtZXMoY29yX3Jlc3VsdF9kZikgPC0gYygiUGFyYW1ldGVycyIsICJDb3JlbGxhdGlvbiIpCiAgZ2dwbG90KGNvcl9yZXN1bHRfZGYsIGFlcyh4PVBhcmFtZXRlcnMsIHk9Q29yZWxsYXRpb24pKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpKQp9CmBgYAoKPGg1PkluZmx1ZW5jZXJzIGZvciBSYXRpbmdzPC9oNT4KYGBge3J9Cmdvb2RfYmFkX2NvcnIoY29yX3Jlc3VsdFsicmF0aW5nIixdKQpgYGAKCjxoNT5JbmZsdWVuY2VycyBmb3IgQ2Fsb3JpZXM8L2g1PgpgYGB7cn0KZ29vZF9iYWRfY29ycihjb3JfcmVzdWx0WyJjYWxvcmllcyIsXSkKYGBgCgo8aDU+V2hhdHMgeW91IGdldCBpbiBvbmUgU2VydmluZzwvaDU+CmBgYHtyfQpkYXRhICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXBzLCBmaWxsID0gbWZyX25hbWVzKSkgKwogICAgICAgIGdlb21faGlzdG9ncmFtKCkgKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIiMgb2YgQ3VwcyIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgICAgIGxhYnMoZmlsbCA9ICJNYW51ZmFjdHVyZXIiLCB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgY3VwcyBwZXIgU2VydmluZyIsCiAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJkaWZmZXJlbnQgY3VwcyBmb3Igc2VydmluZ3MiLCB5PSIjIG9mIFByb2R1Y3RzIikgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKSArIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikKYGBgCgpgYGB7cn0KZGF0YSAlPiUgZ2dwbG90KGFlcyh4ID0gd2VpZ2h0LCBmaWxsID0gbWZyX25hbWVzKSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIldlaWdodCAoaW4gb3VuY2VzKSIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgbGFicyhmaWxsID0gIk1hbnVmYWN0dXJlciIsIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBXZWlnaHQgcGVyIFNlcnZpbmciLCBzdWJ0aXRsZSA9ICJXZWlnaHQgcGVyIHNlcnZpbmciKSArCiAgICB0aGVtZV9jbGFzc2ljKCkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpCmBgYAoKPGg1PkJlc3QgaW4gdGhlIE1hcmtldDwvaDU+CmBgYHtyfQpkIDwtIGRhdGEgJT4lIGFycmFuZ2UocmF0aW5nKSAlPiUgaGVhZCg0KSAlPiUgc2VsZWN0KG5hbWUsIHJhdGluZykKZ2dwbG90KGRhdGE9ZCwgYWVzKHg9bmFtZSwgeT1yYXRpbmcpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgICAgbGFicyh5PSJSYXRpbmdzIikgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpKQpgYGAKCjwvZGl2PgoKPCEtLSAtLS0tLS0tLS0tIC0tLS0tLS0tLS0gLS0tLS0tLS0tLSAtLS0tLS0tLS0tIC0tPgo8ZGl2IGNsYXNzPSJjb250YWluZXItcGFydCI+CjxoMj5QYXJ0ICM6IDwvaDE+CkNvbXBhbnkgd2lzZSBSYXRpbmcgQ29uc2lzdGVuY3kKCmBgYHtyIG91dC53aWR0aD0iMTAwJSJ9CmRhdGFfZ3JwX21mciAlPiUgcGxvdF9seSh5PSB+cmF0aW5nLCB4PSB+bWZyX25hbWVzX2ZhY3RvciwgdHlwZSA9ICJib3giLCBjb2xvcj0gfm1mcl9uYW1lc19mYWN0b3IpICU+JQogIGxheW91dCh0aXRsZT0iUHJvZHVjdCBDb25zaXN0ZW5jeSIsIHhheGlzPWxpc3QodGl0bGU9Ik1hbnVmYWN0dXJlcyIpLCB5YXhpcz1saXN0KHRpdGxlPSJSYXRpbmciKSkKYGBgCgpDb21wYW55IHdpc2UgQ2Fsb3JpZSBDb25zaXN0ZW5jeQpgYGB7ciBvdXQud2lkdGg9IjEwMCUifQpkYXRhX2dycF9tZnIgJT4lIHBsb3RfbHkoeT0gfmNhbG9yaWVzLCB4PSB+bWZyX25hbWVzX2ZhY3RvciwgdHlwZSA9ICJib3giLCBjb2xvcj0gfm1mcl9uYW1lc19mYWN0b3IpICU+JQogIGxheW91dCh0aXRsZT0iUHJvZHVjdCBDb25zaXN0ZW5jeSAoYnkgQ2Fsb3JpZXMpIiwgeGF4aXM9bGlzdCh0aXRsZT0iTWFudWZhY3R1cmVzIiksIHlheGlzPWxpc3QodGl0bGU9IkNhbG9yaWVzIikpCmBgYAo8L2Rpdj4KCjxkaXYgY2xhc3M9ImNvbnRhaW5lci1wYXJ0Ij4KPGgyPlBhcnQgIzogPC9oMT4KCkRpc3RyaWJ1dGlvbiBvZiBSYXRpbmcgdnMgQ2Fsb3JpZSBDYXRlZ29yeQpgYGB7cn0KZGF0YSAlPiUgZ2dwbG90KGFlcyh4ID0gcmF0aW5nLCBmaWxsID0gY2Fsb3JpZXNfY2F0ZWdvcnkpKSArIGdlb21faGlzdG9ncmFtKCkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiUmF0aW5ncyIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgICAgIGxhYnMoZmlsbCA9ICIgQ2FsICIsIHkgPSdDb3VudCcsIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBSYXRpbmcgdnMgQ2Fsb3JpZSBDYXRlZ29yeSIsIHN1YnRpdGxlID0gIkxvdyByYXRpbmcgZm9yIEhpZ2ggY2Fsb3JpZXMiKSArCiAgICAgICAgdGhlbWVfY2xhc3NpYygpCmBgYAoKV29yZCBDbG91ZCAoZXJyb3IgaW4gbWFya2Rvd24pCmBgYHtyfQojZ2V0X2ZpbGVfY29udGVudCA8LSBmdW5jdGlvbiAoKSB7CiMgIHR4dCA8LSByZWFkTGluZXMoImRhdGEvaGVhbHRoLnR4dCIpCiMgIHR4dCA8LSBwYXN0ZSh0eHQsIGNvbGxhcHNlID0gIiAiKQojICB0eHQgPC0gdG9sb3dlcih0eHQpCiMgIHR4dCA8LSBnc3ViKCJbXmEtekEtWl0iLCAiICIsIHR4dCkKIyAgdHh0IDwtIGdzdWIoIlxccysiLCAiICIsIHR4dCkKIyAgdHh0IDwtIHJlbW92ZVdvcmRzKHR4dCwgc3RvcHdvcmRzKCkpCiMgIHdvcmRzIDwtIHN0cnNwbGl0KHR4dCwgIiAiKQojICB3b3JkX2ZyZXEgPC0gdGFibGUod29yZHMpCiMgIHJldHVybiAod29yZF9mcmVxKQojfQojd29yZF9mcmVxIDwtIGdldF9maWxlX2NvbnRlbnQoKQojd29yZGNsb3VkMih3b3JkX2ZyZXEsIHNpemU9MTApCmBgYAoKQ2x1c3RlciBBbmFseXNpcwpgYGB7cn0KY2x1c3Rlcl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChjYWxvcmllcywgcmF0aW5nLCBwcm90ZWluLCBmYXQpICU+JSBzY2FsZQpyb3cubmFtZXMoY2x1c3Rlcl9kYXRhKSA8LSBkYXRhWywxXQprbS5yZXMgPC0ga21lYW5zKGNsdXN0ZXJfZGF0YSwgNSwgbnN0YXJ0ID0gMjUpCmZ2aXpfY2x1c3RlcihrbS5yZXMsIGRhdGE9Y2x1c3Rlcl9kYXRhLCBwYWxldHRlID0gImpjbyIsIGdndGhlbWUgPSB0aGVtZV9taW5pbWFsKCkpCmBgYAoKCg==